package fr.jhaccoun.demenager_eco.utilisateur;

import org.apache.commons.lang.Validate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.encoding.PasswordEncoder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;


@Service("utilisateurService")
@Transactional(readOnly = true)
public class UtilisateurServiceImpl implements UtilisateurService {

	private static final Logger LOGGER = LoggerFactory.getLogger(UtilisateurServiceImpl.class);
	
	
	@Autowired
	private UtilisateurDao utilisateurDao;
	 
	//TODO changer avec salt variable plus tard
	private static final String salt ="julien";
	 
	@Autowired
	private PasswordEncoder passwordEncoder;
	
	
	 	
	@Override
	@Transactional(readOnly = false)
	public void addUtilisateur(Utilisateur utilisateur) throws UserAlreadyExistsException {
		 
		LOGGER.info("Ajout de l'utilisateur : "+utilisateur);
		
		Validate.notNull(utilisateur,"utilisateur ne doit pas être null"); 
		
		Utilisateur utilisateurPersisted = null;
		
		LOGGER.info("Vérification de l'unicité de l'utilisateur");
 
			//FIXME : voir si pas meilleur de catcher l'exception d'unicité lors de l'ajout au lieu de controler, meilleur pour les performance et en general lors de l'ajout d'un user souvent ce dernier existe pas déja en base (unicité sur mail)..
		 
		utilisateurPersisted = findByEmail(utilisateur.getEmail()); 	
		 
		if(utilisateurPersisted != null){
			LOGGER.info("Utilisateur déja existant");
			 throw new UserAlreadyExistsException("utilisateur.error.utilisateurExisteDeja");
		}else{
			LOGGER.info("Nouvel utilisateur");
			utilisateur.setPassword(passwordEncoder.encodePassword(utilisateur.getPassword(),salt));
			utilisateurDao.save(utilisateur);
			LOGGER.info("Sauvegarde de l'utilisateur effectué");
		} 
	}
	 
	
	 
	@Transactional(readOnly = false)
	public void createUser(UserDetails user) {
		utilisateurDao.save((Utilisateur) user);
	}

	@Transactional(readOnly = false)
	public void updateUser(UserDetails user) {
		utilisateurDao.save((Utilisateur) user);
	}

	@Transactional(readOnly = false)
	public void deleteUser(String username) {
		utilisateurDao.delete(Long.valueOf(username));
	}
 
	@Transactional(readOnly = false)
	public void changePassword(String oldPassword, String newPassword) { 
	//TODO IMPLEMENTER
	}
 

	@Transactional(readOnly = true)
	public boolean userExists(String username) { 
		return utilisateurDao.findByEmail(username) != null ? true : false;
	}
	  
	@Override
	@Transactional(readOnly = true)
	public Utilisateur findByEmail(String email) { 
		Validate.notEmpty(email);
		return utilisateurDao.findByEmail(email); 
	}
	
	@Override
	@Transactional(readOnly = true) 
	public Utilisateur getUtilisateurById(long id) { 
		return utilisateurDao.findOne(id); 
	}
	
	@Override
	@Transactional(readOnly = true) 
	public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { 
		UserDetails utilisateur = utilisateurDao.findByEmail(username);
 
		if (utilisateur == null) {
			throw new UsernameNotFoundException("Aucun utilisateur identifié avec email: " + username + ".");
		}

		return utilisateur;

	}
	
	@Override
	@Transactional(readOnly = false)
	public void updateUtilisateur(Utilisateur utilisateur) {
		Validate.notNull(utilisateur,"utilisateur");
		Validate.notNull(utilisateur.getId(),"id");

		LOGGER.info("Mise à jour de l'utilisateur:{}",utilisateur);

		utilisateurDao.save(utilisateur); 
	}
	
	@Override
	@Transactional(readOnly = true) 
	public Utilisateur getCurrentUser() {
		return utilisateurDao.getCurrentUser();
	}
	
	@Override
	@Transactional(readOnly = true) 
	public boolean isLogged() {
		return utilisateurDao.isLogged();
	}
	
	@Override
	@Transactional(readOnly = true) 
	public void autoLogUser(Utilisateur utilisateur) {
		Validate.notNull(utilisateur);
		
		utilisateurDao.autoLogUser(utilisateur);
	}
}
